package twel.probenprophet.profile.spells.xdiml2.jaxb;

import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import org.apache.commons.lang3.StringUtils;

import twel.probenprophet.base.enums.AllowedModification;
import twel.probenprophet.base.enums.Attribute;
import twel.probenprophet.base.enums.Complexity;
import twel.probenprophet.base.enums.Trait;
import twel.probenprophet.base.exceptions.ProbenprophetException;
import twel.probenprophet.base.utility.Triple;

@XmlAccessorType(XmlAccessType.FIELD)
public class SpellDefinition {

	@XmlAttribute(name = "ID")
	private String name;

	@XmlElement(name = "Komplexität")
	private Complexity complexity;

	@XmlElement(name = "Probe")
	@XmlJavaTypeAdapter(value = AttributeTripleAdapter.class)
	private Triple<Attribute> checkAttributes;

	@XmlElementWrapper(name = "Merkmale")
	@XmlElement(name = "Merkmal")
	private Collection<Trait> traits;

	@XmlElementWrapper(name = "Modifikationen")
	@XmlElement(name = "Spontan")
	private Collection<AllowedModification> allowedModifications;

	@XmlElementWrapper(name = "Varianten")
	@XmlElement(name = "Variante")
	private Collection<String> variants; // TODO spomods/varianten trennen

	public SpellDefinition() {
	}

	public SpellDefinition(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Complexity getComplexity() {
		return complexity;
	}

	public void setComplexity(Complexity complexity) {
		this.complexity = complexity;
	}

	public Triple<Attribute> getCheckAttributes() {
		return checkAttributes;
	}

	public String getCheckAttributesAsString() {
		return checkAttributes.toString();
	}

	public void setCheckAttributes(Triple<Attribute> attributes) {
		this.checkAttributes = attributes;
	}

	public EnumSet<Trait> getTraits() {
		return EnumSet.copyOf(traits);
	}

	public void setTraits(EnumSet<Trait> traits) {
		this.traits = traits;
	}

	public EnumSet<AllowedModification> getAllowedModifications() {
		return EnumSet.copyOf(allowedModifications);
	}

	public void setAllowedModifications(EnumSet<AllowedModification> allowedModifications) {
		this.allowedModifications = allowedModifications;
	}

	public Collection<String> getVariants() {
		return variants;

		// Set<String> noSpoMods;
		//
		// if (variants == null) {
		// noSpoMods = new HashSet<String>();
		// } else {
		// noSpoMods = new HashSet<String>(variants);
		// }
		//
		// for (SpontaneousModification spontaneousModification :
		// SpontaneousModification.values()) {
		// if (variants != null &&
		// variants.contains(spontaneousModification.toString())) {
		// noSpoMods.remove(spontaneousModification.toString());
		// }
		// }
		//
		// return noSpoMods;
	}

	public void setVariants(Collection<String> variants) {
		this.variants = variants;
	}

	@Override
	public String toString() {
		return name + " " + checkAttributes;
	}

	private static class AttributeTripleAdapter extends XmlAdapter<String, Triple<Attribute>> {

		@Override
		public Triple<Attribute> unmarshal(String string) throws Exception {
			Pattern pattern = Pattern.compile("^(\\w+)/(\\w+)/(\\w+)$");
			Matcher matcher = pattern.matcher(string);

			if (matcher.matches()) {
				Attribute attribute1 = Attribute.valueOf(matcher.group(1));
				Attribute attribute2 = Attribute.valueOf(matcher.group(2));
				Attribute attribute3 = Attribute.valueOf(matcher.group(3));

				return new Triple<Attribute>(attribute1, attribute2, attribute3);
			}

			throw new ProbenprophetException("malformed string");
		}

		@Override
		public String marshal(Triple<Attribute> attributeTriple) throws Exception {
			List<Attribute> list = attributeTriple.getList();
			return StringUtils.join(list, "/");
		}

	}
}
